<template>
  <div class="box" ref="box">
    <div
      class="ball"
      :style="{
        left: ballPosition.x + 'px',
        top: ballPosition.y + 'px'
      }"
      ref="ball"
    ></div>
  </div>
</template>

<script setup>
import { onMounted, reactive, ref } from 'vue'
const box = ref()
const ball = ref()
const ballPosition = reactive({
  x: 0,
  y: 0
})

onMounted(() => {
  window.addEventListener('click', (e) => {
    if (e.target.className === 'box') {
      const rect = box.value.getBoundingClientRect()
      const x = e.clientX - rect.x
      const y = e.clientY - rect.y
      move(x, y)
    }
  })
})

const move = (x, y) => {
  const ballRect = ball.value.getBoundingClientRect()
  const boxRect = box.value.getBoundingClientRect()
  const initX = ballRect.left - boxRect.left + ballRect.width / 2
  const initY = ballRect.top - boxRect.top + ballRect.height / 2
  const rad = Math.atan2(y - initY, x - initX)
  const deg = (rad * 180) / Math.PI
  ball.value.getAnimations().forEach((item) => {
    item.cancel()
  })

  ball.value.animate(
    [
      {
        transform: `translate(${initX}px,${initY}px) rotate(${deg}deg)`,
        easing: 'ease-out'
      },
      {
        transform: `translate(${initX}px,${initY}px) rotate(${deg}deg) scaleX(1.6)`,
        offset: 0.6
      },
      {
        transform: `translate(${x}px,${y}px) rotate(${deg}deg) scaleX(1.6)`,
        offset: 0.8,
        easing: 'ease-in'
      },
      {
        transform: `translate(${x}px,${y}px) rotate(${deg}deg)`
      }
    ],
    {
      duration: 500,
      fill: 'forwards'
    }
  )
}
</script>

<style lang="scss" scoped>
.box {
  width: 100%;
  height: 100%;
  background-color: #000;
  position: relative;
  overflow: hidden;
}

.ball {
  position: absolute;
  width: 100px;
  height: 100px;
  background-color: red;
  border-radius: 50%;
  margin-left: -50px;
  margin-top: -50px;
}
</style>
